
#include "cl_programs/common/header.h"

static cl_program program;
static cl_kernel hKernel;

void initMutInfoGPU(cl_context in_context, cl_device_id in_device)
{
	cl_int error;
	size_t src_size;
	const char *path = shrFindFilePath("pearson.cl", NULL);
	char *source = oclLoadProgSource( path, "", &src_size);
	shrCheckError(source != NULL, shrTRUE);
	program = clCreateProgramWithSource(in_context, 1, (const char **)&source, &src_size, &error);
	assert(error == CL_SUCCESS);

	error = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
	assert(error == CL_SUCCESS);

	char *build_log;
	size_t log_size;

	clGetProgramBuildInfo(program, in_device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);
	build_log = new char[log_size+1];

	clGetProgramBuildInfo(program, in_device, CL_PROGRAM_BUILD_LOG, log_size, build_log, NULL);
	build_log[log_size] = '\0';
	printf("%s\n", build_log);
	free(build_log);

	hKernel = clCreateKernel(program, "MutualInfo", &error);
	assert(error == CL_SUCCESS);
	free(source);
}

void closeMutInfoGPU(void)
{
    cl_int error;
    error  = clReleaseKernel(hKernel);
    error |= clReleaseProgram(program);
    shrCheckError(error, CL_SUCCESS);
}

void MutInfoGPU(cl_command_queue hCmdQueue, cl_mem in_info, cl_mem in_arr, cl_int in_M, cl_int in_NUM_ROWS)
{
	cl_int error;
	size_t localWorkSize = in_NUM_ROWS;
	size_t globalWorkSize = in_NUM_ROWS;

	error = clSetKernelArg(hKernel, 0, sizeof(cl_mem), (void *)&in_info);
	assert(error == CL_SUCCESS); 
	error |= clSetKernelArg(hKernel, 1, sizeof(cl_mem), (void *)&in_arr);
	assert(error == CL_SUCCESS);
	error |= clSetKernelArg(hKernel, 2, sizeof(cl_int), (void *)&in_M);
	assert(error == CL_SUCCESS);
	error |= clSetKernelArg(hKernel, 3, sizeof(cl_int), (void *)&in_NUM_ROWS);
	assert(error == CL_SUCCESS);

	//clGetKernelWorkGroupInfo(hKernel, NULL, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &localWorkSize, NULL);
	//printf("\n CL_KERNEL_WORK_GROUP_SIZE: %i\n" , localWorkSize); 

	error = clEnqueueNDRangeKernel(hCmdQueue, hKernel, 1, NULL, &globalWorkSize, &localWorkSize, 0, NULL, NULL);
	assert(error == CL_SUCCESS);
}